package main

import (
	"fmt"
	"strconv"
	"sync"
)

// sync.Map go语言中原生的map不是并发的，在多个goroutine操作map时，可能会出现数据数据的丢失
// 对key-value没有限制
func main() {
	var syncMap sync.Map
	var wg sync.WaitGroup

	//Store
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			syncMap.Store(i, "hello-world-"+strconv.Itoa(i))
		}(i)
	}
	//Load
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			value, ok := syncMap.Load(i)
			if ok {
				switch value.(type) {
				case string:
					fmt.Println(value.(string))
				case bool:
					fmt.Println(value.(bool))
				case int:
					fmt.Println(value.(int))
				default:
					fmt.Println("unknow")

				}
			}
		}(i)
	}
	actual, loaded := syncMap.LoadOrStore(110, "hello-world-"+strconv.Itoa(110))
	fmt.Println("v:", actual, "ex:", loaded) //v: hello-world-110 ex: false

	actual1, loaded1 := syncMap.LoadOrStore(110, "hello-world-"+strconv.Itoa(111))
	fmt.Println("v:", actual1, "ex:", loaded1) //v: hello-world-110 ex: true

	value, ok := syncMap.Load(110)
	if ok {
		fmt.Println(value) //hello-world-110
	}

	andDelete, l := syncMap.LoadAndDelete(110)
	if l {
		fmt.Println(andDelete) //hello-world-110
	} else {
		fmt.Println("not found")
	}
	andDelete1, l1 := syncMap.LoadAndDelete(110)
	if l1 {
		fmt.Println(andDelete1)
	} else {
		fmt.Println("not found") //not found
	}

	wg.Wait()

	syncMap.Range(func(key, value interface{}) bool {
		fmt.Println(key, value)
		return true
	})

	fmt.Println("map添加数据完成~")

}

// test
//
//	@Description: 原生map有并发安全问题
func test() {
	var oMap map[int]string = make(map[int]string)
	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			oMap[i] = "hello-world" + strconv.Itoa(i)
		}(i)
	}
	wg.Wait()
	fmt.Println("map添加数据完成~")
	for k, v := range oMap {
		fmt.Println(k, v)
	}
}
